package com.rljk.utils.security;

import org.apache.commons.codec.binary.Base64;

import java.security.*;
import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

/**
 * Author:   YASUO
 * Date:     2018/7/10 10:42
 * Description:椭圆曲线数字签名算法（ECDSA）是使用椭圆曲线密码（ECC）对数字签名算法（DSA）的模拟
 */
public class ECDSA {

    static String src = "欧阳草帽";

    public static void main(String[] args) throws Exception {
        // TODO Auto-generated method stub

        // 获取公钥、私钥
        KeyPair keyPair = getKeyPair();

        ECPublicKey ecPublicKey = getRSPublicKey(keyPair);
        ECPrivateKey ecPrivateKey = getESAPrivateKey(keyPair);
        byte [] publicKeyEnc = ecPublicKey.getEncoded();   // 公钥
        byte [] privateKeyEnc = ecPrivateKey.getEncoded(); //私钥

        //执行签名
        byte[] result = sign(privateKeyEnc);
        System.out.println("签名后的数据："+ Base64.encodeBase64String(result));

        //验证签名
        boolean ok = verify(publicKeyEnc, result);
        System.out.println("签名验证的结果：" + ok);
    }
    /**
     * 验证签名
     * @param publicKeyEnc
     * @param result
     * @return
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeySpecException
     * @throws InvalidKeyException
     * @throws SignatureException
     */
    public static boolean verify(byte[] publicKeyEnc, byte[] result)
            throws NoSuchAlgorithmException, InvalidKeySpecException,
            InvalidKeyException, SignatureException {
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKeyEnc);
        KeyFactory keyFactory = KeyFactory.getInstance("EC");
        PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
        Signature signature = Signature.getInstance("SHA1withECDSA");
        signature.initVerify(publicKey);
        signature.update(src.getBytes());
        boolean ok = signature.verify(result);  // 验证结果
        return ok;
    }

    /**
     * 执行签名
     * @param privateKeyEnc
     * @return
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeySpecException
     * @throws InvalidKeyException
     * @throws SignatureException
     */
    public static byte[] sign(byte[] privateKeyEnc)
            throws NoSuchAlgorithmException, InvalidKeySpecException,
            InvalidKeyException, SignatureException {
        KeyFactory keyFactory = KeyFactory.getInstance("EC");
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKeyEnc);
        PrivateKey priKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
        //构建签名
        Signature signature = Signature.getInstance("SHA1withECDSA");
        signature.initSign(priKey);
        signature.update(src.getBytes());
        byte [] result = signature.sign();   // 签名后的数据信息
        return result;
    }

    /**
     * 生成私钥
     * @param keyPair
     * @return
     */
    public static ECPrivateKey getESAPrivateKey(KeyPair keyPair) {
        ECPrivateKey ecPrivateKey = (ECPrivateKey) keyPair.getPrivate();
        return ecPrivateKey;
    }

    /**
     * 生成公钥
     * @param keyPair
     * @return
     */
    public static ECPublicKey getRSPublicKey(KeyPair keyPair) {
        ECPublicKey ecPublicKey = (ECPublicKey) keyPair.getPublic();
        return ecPublicKey;
    }

    /**
     * 生成秘钥对的材料
     * @return
     * @throws NoSuchAlgorithmException
     */
    private static KeyPair getKeyPair() throws NoSuchAlgorithmException {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC");
        keyPairGenerator.initialize(256);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        return keyPair;
    }

}
